﻿/////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008 by Jamesvon, Inc.
// All Rights Reserved.
//
// 文件名：         VonFunctions.cs
// 创建人：         James von
// 创建日期：       2012-4-1 8:00:00
// 文件功能描述：   通用函数及结构
//
// 慎重声明：
//
// 本软件包含版权资料、商业秘密以及其他财产资料。用户不可，也不能试图对本软件
// 进行修改、反向工程改造、拆解或反编译，也不能抽取或盗取本软件的组成部分用于
// 生成派生产品或其它产品。
// James von 的名字和代表其软件产品的标记、图案等，不能以任何理由、任何方式
// 用于推广基于本软件之上开发的其它产品。
// James von 保留本软件的所有权利、资格、利益以及此处所涉及到的所有知识产权。
// James von 的所有软件和产品的组成部分均受版权法和国际版权公约保护。除了单
// 用户许可证规定的权限以外，用户不能以任何理由任何方式复制或使用James von的
// 程序、代码、组件、图像、影像剪辑、声音样本以及文本。除了明确的书面授权外，
// James von保留所有的权利。
//
//修订历史记录：
//
//
/////////////////////////////////////////////////////////////////////////////
// VonKeyValueItem  键值对,{key}={value},{string}={string}
//---------------------------------------------------------------------------
//      键值对的基本类型，以两个字符串类作为基础信息，存储配对信息。
//===========================================================================
// VonObjectItem    键值单元,{key}={value}+{data},{string}={string}+{object}
//---------------------------------------------------------------------------
//      以键值对的基本类型，增加对象存储单元，作为扩展信息使用。
//===========================================================================
// VonLinkerItem    链接单元，作为链结构的基础但愿存在。
//---------------------------------------------------------------------------
//      具有本级内容，和前后单元连接。
//===========================================================================
// VonLinkerCollection  链表结构
//---------------------------------------------------------------------------
//      可以处理链结构的信息处理，支持前后追溯，支持头尾直查。
//===========================================================================
// VonKeyValueCollection    键值对集合(Key=Value)，支持文本输出和输入
//---------------------------------------------------------------------------
//      默认文本输出格式为：{key}#3{value}$5...{key}#3{value}$5
//===========================================================================
// VonStringCollection  字符键值集合(含应用对象)，支持文本输出和输入
//---------------------------------------------------------------------------
//      可以通过 Delimiter 和 Termination 来定义输出间隔符号。
//===========================================================================
// VonConfigCollection  类型配置信息管理类
//---------------------------------------------------------------------------
//      采用hashtable进行存储，支持段落和
//===========================================================================
// EVonParamDelimiterScheme 参数设置间隔符方案
//---------------------------------------------------------------------------
//      支持几种间隔方式存储：
//      EVPDS_Custom:用户手动定义的间隔符
//      EVPDS_Comma:{section}:{key}={value},...\r
//      EVPDS_Semicolon:{section}:{key}={value};...\r
//      EVPDS_Bracket:{section}={key}({value})...\r
//      EVPDS_Special:{section}#3{key}#4{value}#5...#7
//===========================================================================
// VonParamItem 参数集合支持   
//---------------------------------------------------------------------------
//      name=key1(value1)key2(value2)...，
//  同样也支持name=key1=value1,key2=value2,...，
//  或者name#3key1#3value1#3key2#3value2#3...#4
//===========================================================================
// VonParamCollection   含键值的参数集合
//---------------------------------------------------------------------------
//      可以通过 TextScheme（EVonParamDelimiterScheme）来定义存储和输出的文本格式
//===========================================================================
// VonFuns   常用函数集合
//---------------------------------------------------------------------------
//      ConvertStrToUrl(string) 将URL信息转换为可传递的参数类型
//      ConvertUrlToStr(string) 将参数信息转换为可传递的URL类型
//      CurrencyToGB(double)    将金额转换为中文大写
//      FindStr(string,string)  查找一个字符串，排除中间的引号内容。
//      GetCheckItem(System.Web.UI.WebControls.CheckBoxList)    根据 CheckBoxList 生成字符串（以逗号做间隔符）类型的选择结果
//      GetCheckValue(System.Web.UI.WebControls.CheckBoxList)   CheckBoxList 选择结果，以二进制方式进行存储
//      GetRandomColor()        得到一个序列颜色字符串值
//      isNumberic(string)      判断是否为数字字符串
//      NumToGB(double)         将数值转换为中文大写
//      SetCheckItem(System.Web.UI.WebControls.CheckBoxList,string) 根据字符串（以逗号做间隔符），设置 CheckBoxList 选择结果
//      SetCheckValue(System.Web.UI.WebControls.CheckBoxList,int)   根据值，按照二进制位设置 CheckBoxList 选择结果
//      SplitString(string,string,string,string)    将字符串转换为数组
//      SplitString(string,string,int,int)          将字符串转换为数组（截取时包含起始和截取位置）
//===========================================================================
using System;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Collections;
using System.Text;
using System.ComponentModel;
using System.Reflection;
using System.Globalization;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Linq;

namespace Von.Library
{
    public static class Consts
    {
        static public readonly DateTime MinDBDate = new DateTime(1900, 1, 1, 0, 0, 0);
        //64字节转换用字符集，可以通过 Disorder 函数进行乱序生成//ABCDEFGHIJKLMNOPQRSTUVWXYZ.1234567890_abcdefghijklmnopqrstuvwxyz
        public const string CryptValue = "WjubT76xE3NZg01cyw9qAF2O4DndYfGKtvBJsQ8ePMiz_Lp5omURIlkV.SCrhHXa";
                           //有效字符集，"ABCDEFGHIJKLMNOPQRSTUVWXYZ@1234567890-abcdefghijklmnopqrstuvwxyz"
                                        //         1         2         3         4         5         6  
                                        //0123456789012345678901234567890123456789012345678901234567890123
    }
    /// <summary>
    /// 
    /// </summary>
    public static class Functions
    {
        #region "数字转换相关函数"
        /// <summary>
        /// 将金额转换为中文大写
        /// </summary>
        /// <param name="value">金额值</param>
        /// <returns>中文表达的金额值</returns>
        public static string CurrencyToGB(double value)
        {
            const string gbValue = "零壹贰叁肆伍陆柒捌玖";
            const string gbUnit = "分角元拾佰仟万拾佰仟亿拾佰仟万";

            string result = "";

            if (value < 0)
            {
                result = "负";
                value = -value;
            }
            string szStr = ((int)(value * 100 + 0.5)).ToString();
            for (int i = 0; i < szStr.Length; i++)
            {
                result += gbValue[szStr[i] - '0'];
                result += gbUnit[szStr.Length - i - 1];
            }
            result = result.Replace("零仟", "零");
            result = result.Replace("零佰", "零");
            result = result.Replace("零拾", "零");
            result = result.Replace("零角", "零");
            result = result.Replace("零分", "整");
            result = result.Replace("零零", "零");
            result = result.Replace("零零", "零");
            result = result.Replace("零亿", "亿");
            result = result.Replace("零万", "万");
            result = result.Replace("零元", "元");
            if (result == "整") result = "零元整";
            else
            {
                result = result.Replace("亿万", "亿");
                result = result.Replace("零整", "整");
            }
            return result;
        }

        /// <summary>
        /// 将数值转换为中文大写
        /// </summary>
        /// <param name="value">数值</param>
        /// <returns>中文表达的数值</returns>
        public static string NumToGB(double value)
        {
            const string gbValue = "零壹贰叁肆伍陆柒捌玖";
            const string gbUnit = "点拾佰仟万拾佰仟亿拾佰仟万";

            string result = "";

            if (value < 0)
            {
                result = "负";
                value = -value;
            }
            string szStr = value.ToString();
            int zeroPos = szStr.IndexOf('.');
            if (zeroPos == 0) zeroPos = szStr.Length;
            for (int i = 0; i < szStr.Length; i++)
            {
                if (szStr[i] != '.') result += gbValue[szStr[i] - '0'];
                if (zeroPos - i > 0) result += gbUnit[zeroPos - i - 1];
            }
            result = result.Replace("零仟", "零");
            result = result.Replace("零佰", "零");
            result = result.Replace("零拾", "零");
            result = result.Replace("零零", "零");
            result = result.Replace("零零", "零");
            result = result.Replace("零亿", "亿");
            result = result.Replace("零万", "万");
            if (result.EndsWith("壹拾")) result.Remove(result.Length - 1);
            result = result == "零点" ? result = "零" : result = result.Replace("零点", "点");
            if (result.EndsWith("点")) result.Remove(result.Length - 1);
            return result.Replace("亿万", "亿");
        }

        public static double HexToDouble(string Hex)
        {
            double result = 0;
            for (int i = 0; i < Hex.Length; i++) { result = result * 16 + "0123456789ABCDEF".IndexOf(Hex[i], StringComparison.OrdinalIgnoreCase); }
            return result;
        }
        #endregion
        #region "字符串转换相关函数"
        /// <summary>
        /// 随机生成指定长度的字符串
        /// </summary>
        /// <param name="len"></param>
        /// <returns></returns>
        public static string RandomStr(int len)
        {
            StringBuilder sb = new StringBuilder();
            Random rd = new Random();
            for (int i = 0; i < len; i++)
            {
                sb.Append(Von.Library.Consts.CryptValue[rd.Next(64)]);
            }
            return sb.ToString();
        }
        /// <summary>
        /// 将GUID转换为系统唯一码（22位字符）
        /// </summary>
        /// <param name="gid"></param>
        /// <returns></returns>
        public static string GuidToStr(Guid gid)
        {
            return BytesToStr(gid.ToByteArray());
        }
        /// <summary>
        /// 查找一个字符串，排除中间的引号内容。
        /// </summary>
        /// <param name="S">被查找的字符串</param>
        /// <param name="subStr">要找到的字符串</param>
        /// <returns>位置，从0开始，未找到为-1</returns>
        public static int FindStr(string S, string subStr)
        {
            if (subStr == "") return 0;
            string szS = "";
            char nextChar = '\x0000';
            int idx = 0;
            foreach (char ch in S)
            {
                switch (ch)
                {
                    case '"':
                    case '\x0027':
                        if (nextChar == ch) nextChar = '\x0000';
                        else nextChar = ch; szS = "";
                        break;
                    default: if (nextChar == '\x0000') szS += ch; break;
                }
                idx++;
                if (szS.Length > subStr.Length) szS = szS.Remove(0, 1);
                if (szS.Equals(subStr, StringComparison.CurrentCultureIgnoreCase)) return idx - subStr.Length;
            }
            return -1;
        }
        /// <summary>
        /// 将字符串转换为数组
        /// </summary>
        /// <param name="S">字符串</param>
        /// <param name="flags">换行标记，例如“&\\?”</param>
        /// <param name="startFlag">起始字符标记，如果没有可以用""表示</param>
        /// <param name="endFlag">结束字符标记，如果没有可以用""表示</param>
        /// <returns>数组</returns>
        public static List<string> SplitString(string S, string flags, string startFlag, string endFlag)
        {
            List<string> result = new List<string>();

            string szStart = "";
            string szEnd = "";
            string szValue = "";
            char nextChar = '\x0000';
            bool isStart = startFlag == "";
            foreach (char ch in S)
            {
                switch (ch)
                {
                    case '"':
                    case '\x0027':
                        if (nextChar == ch) nextChar = '\x0000';
                        else nextChar = ch; szStart = ""; szEnd = "";
                        break;
                    default:
                        if (nextChar == '\x0000')
                        {
                            szStart += ch;
                            szEnd += ch;
                            if (szStart.Length > startFlag.Length) szStart = szStart.Remove(0, 1);
                            if (szEnd.Length > endFlag.Length) szEnd = szEnd.Remove(0, 1);
                        }
                        break;
                }
                if (isStart)
                {
                    if (nextChar == '\x0000' && flags.IndexOf(ch) >= 0)
                    {
                        if (!string.IsNullOrEmpty(szValue))
                        {
                            result.Add(szValue);
                            szValue = "";
                        }
                    }
                    else szValue += ch;
                }
                if (isStart && szEnd != "" && szEnd.Equals(endFlag, StringComparison.CurrentCultureIgnoreCase))
                {
                    szValue = szValue.Remove(szValue.Length - endFlag.Length);
                    break;
                }
                if (!isStart && szStart.Equals(startFlag, StringComparison.CurrentCultureIgnoreCase))
                {
                    szValue = "";
                    isStart = true;
                }
            }
            if (szValue != "") result.Add(szValue);
            return result;
        }
        /// <summary>
        /// 将字符串转换为数组（截取时包含起始和截取位置）
        /// </summary>
        /// <param name="S">字符串</param>
        /// <param name="flags">换行标记，例如“&\\?”</param>
        /// <param name="startIdx">起始位置（包含）从0开始</param>
        /// <param name="endIdx">结束位置（包含）,0表示全部</param>
        /// <returns>数组</returns>
        public static List<string> SplitString(string S, string flags, int startIdx, int endIdx)
        {
            List<string> result = new List<string>();
            if (S.Length <= startIdx) return result;
            if (endIdx >= S.Length || endIdx == 0) endIdx = S.Length - 1;
            string szValue = "";
            char nextChar = '\x0000';
            for (int i = startIdx; i <= endIdx; i++)
            {
                char ch = S[i];
                switch (ch)
                {
                    case '"':
                    case '\x0027':
                        if (nextChar == ch) nextChar = '\x0000';
                        else nextChar = ch;
                        break;
                }
                if (nextChar == '\x0000' && flags.IndexOf(ch) >= 0)
                {
                    result.Add(szValue); szValue = "";
                }
                else szValue += ch;
            }
            if (szValue != "") result.Add(szValue);
            return result;
        }
        /// <summary>
        /// 将URL字符串解码为可读URL内容
        /// </summary>
        /// <param name="url">url地址</param>
        /// <returns></returns>
        public static string UrlDecode(string url)
        {
            //将Url中的编码转换为简体汉字
            return System.Web.HttpUtility.UrlDecode(url, System.Text.Encoding.GetEncoding("utf-8"));
            //return System.Web.HttpUtility.UrlDecode(url, System.Text.Encoding.GetEncoding("GB2312"));
        }
        /// <summary>
        /// 将URL内容加码为可使用的URL字符串
        /// </summary>
        /// <param name="value">参数类型</param>
        /// <returns>URL信息</returns>
        public static string UrlEncode(string str)
        {
            //将简体汉字转换为Url编码
            return System.Web.HttpUtility.UrlEncode(str, System.Text.Encoding.GetEncoding("GB2312"));
        }
        /// <summary>
        /// 将 byte 数组转换为十六进制字符串
        /// </summary>
        /// <param name="Value">byte 数组</param>
        /// <returns>十六进制数</returns>
        public static string BytesToHex(byte[] Value)
        {
            string x = "";
            foreach (byte b in Value) x += b.ToString("x2");
            return x;
        }
        /// <summary>
        /// 将 byte 数组转换为可视文字，采用 64 进制转换
        /// </summary>
        /// <param name="Value">byte 数组</param>
        /// <returns>可视文字，长度为数组长度的 4/3，余数加 1 </returns>
        public static string BytesToStr(byte[] Value)
        {
            string strResult = "";
            int idx = 0, val = 0;
            /*----+---------+---------+---------+RTN+-----
                  |AA11 1111|         |         | 1 |           11 1111
                  |0000 0000|BBBB 2222|         | 2 |           2222 AA
                  |0000 0000|0000 1111|11       | 3 |           33 BBBB
                  |0000 0000|0000 0000|CCCC CC33| 4 |           CCCC CC
            --BYTE|1--------+2--------+3--------+---+-----    */
            do
            {
                switch (idx % 3)
                {
                    case 0:
                        strResult += Consts.CryptValue[Value[idx] & 0x3F];                 //1111 11                        1
                        val = Value[idx] >> 6;                                               //---- --VV
                        break;
                    case 1:
                        strResult += Consts.CryptValue[val + (Value[idx] << 2) & 0x3F];    //0000 0011 1111                 2
                        val = Value[idx] >> 4;                                               //       VV(----VVVV)
                        break;                                                               //0         1         2
                    case 2:
                        strResult += Consts.CryptValue[val + (Value[idx] << 4) & 0x003F];  //               1111 11         3
                        strResult += Consts.CryptValue[(Value[idx] >> 2) & 0x003F];        //0000 0000 0000 0000 0011 1111  4
                        val = 0;                                                             //               VVVV--,-- ----
                        break;                                                               //0         1         2        
                }
            } while (++idx < Value.Length);
            if (idx % 3 > 0)
                strResult += Consts.CryptValue[val];
            return strResult;
        }
        /// <summary>
        /// 将可视文字，转换为 byte 数组
        /// </summary>
        /// <param name="Value">可视文字</param>
        /// <returns>byte数组</returns>
        public static byte[] StrToBytes(string Value)
        {
            byte[] byteToConvert = new byte[Value.Length];
            int idx = 0; byte val = 0;
            for (int i = 0; i < Value.Length; i++)
            {
                val = (byte)Consts.CryptValue.IndexOf(Value[i]);
                switch (i % 4)
                {
                    case 0: byteToConvert[idx] = (byte)val; break;
                    case 1: byteToConvert[idx] = (byte)(byteToConvert[idx] | (val << 6)); byteToConvert[++idx] = (byte)(val >> 2); break;
                    case 2: byteToConvert[idx] = (byte)(byteToConvert[idx] | (val << 4)); byteToConvert[++idx] = (byte)(val >> 4); break;
                    case 3: byteToConvert[idx] = (byte)(byteToConvert[idx++] | val << 2); break;
                }
            }
            byte[] result = new byte[idx];
            Array.Copy(byteToConvert, result, idx);
            return result;
        }
        /// <summary>
        /// 字符串转换为Guid值，空值为Guid.Empty
        /// </summary>
        /// <param name="Value"></param>
        /// <returns></returns>
        public static Guid StrToGuid(string Value)
        {
            if (string.IsNullOrEmpty(Value)) return Guid.Empty; else return Guid.Parse(Value);
        }
        /// <summary>
        /// 格式化字符串
        /// </summary>
        /// <param name="format">格式，以@{fieldname}</param>
        /// <param name="data">键值数据{fieldname=fieldvalue}</param>
        /// <returns></returns>
        public static string VonFormat(string format, Dictionary<string, object> data)
        {
            int idx = format.IndexOf("@{");
            while (idx >= 0)
            {
                int end = format.IndexOf("}", idx);
                string field = format.Substring(idx + 2, end - idx - 2);
                format = format.Replace(format.Substring(idx, end - idx + 1), data[field].ToString());
                idx = format.IndexOf("@{");
            }
            return format;
        }
        #endregion
        #region "颜色相关函数"
        public static readonly string[] VonColorDefined = new string[] {
            "#8B0016","#B2001F","#C50023","#DF0029","#E54646","#EE7C6B","#F5A89A","#8E1E20",
            "#B6292B","#C82E31","#E33539","#EB7153","#F19373","#F6B297","#945305","#BD6B09",
            "#D0770B","#EC870E","#F09C42","#F5B16D","#FACE9C","#976D00","#C18C00","#D59B00",
            "#F1AF00","#F3C246","#F9CC76","#FCE0A6","#9C9900","#C7C300","#DCD800","#F9F400",
            "#FCF54C","#FEF889","#FFFAB3","#367517","#489620","#50A625","#5BBD2B","#83C75D",
            "#AFD788","#C8E2B1","#006241","#007F54","#008C5E","#00A06B","#00AE72","#67BF7F",
            "#98D0B9","#00676B","#008489","#009298","#00A6AD","#00B2BF","#6EC3C9","#99D1D3",
            "#103667","#184785","#1B4F93","#205AA7","#426EB4","#7388C1","#94AAD6","#211551",
            "#2D1E69","#322275","#3A2885","#511F90","#635BA2","#8273B0","#38044B","#490761",
            "#52096C","#5D0C7B","#79378B","#8C63A4","#AA87B8","#64004B","#780062","#8F006D",
            "#A2007C","#AF4A92","#C57CAC","#D2A6C7","#ECECEC","#D7D7D7","#C2C2C2","#B7B7B7",
            "#A0A0A0","#898989","#707070","#363636"};
        public static readonly string[] VonColorDefine = new string[]{
            "#FFFFCC","#CCFFFF","#FFCCCC","#99CCCC","#FFCC99","#FFCCCC","#FF9999","#996699",    //1
            "#FFCCCC","#CC9999","#FFFFCC","#CCCC99","#FFCCCC","#FFFF99","#CCCCFF","#0099CC",
            "#CCCCCC","#FF6666","#FF9966","#FF6666","#FFCCCC","#CC9966","#666666","#CC9999",
            "#FF6666","#FFFF66","#99CC66","#CC3333","#CCCCCC","#003366","#993333","#CCCC00",
            "#663366","#CCCC99","#666666","#CC9999","#FF6666","#FFFF00","#0066CC","#CC0033",
            "#333333","#CCCC00","#336633","#990033","#FFCC99","#993333","#CC9966","#003300",
            "#FF0033","#333399","#CCCC00","#CC0033","#003399","#99CC00","#CC0033","#999933",
            "#993333","#333300","#FFCC99","#FFFF99","#99CC99","#FFCC99","#CCFF99","#CCCCCC",
            "#FFCC99","#FFFFCC","#99CCFF","#FF9966","#FFFFCC","#99CC99","#FF9900","#FFFFCC",
            "#336699","#CCCC33","#FFFF99","#CC9933","#996600","#FFCC33","#FFFFCC","#FFFFCC",    //10
            "#CC9933","#336666","#FF9900","#FFFF00","#0099CC","#99CC33","#FF9900","#FFCC00",
            "#FF9933","#99CC33","#CC6699","#FF9933","#FFFF00","#3366CC","#FF9933","#FFFFCC",
            "#009966","#FF6600","#FFFF66","#009966","#990033","#CCFF66","#FF9900","#FF9966",
            "#996600","#CCCC00","#CC6600","#999999","#CCCC33","#CC6600","#CCCC33","#336699",
            "#FF9933","#999966","#663300","#FF9933","#FFFF66","#FFFFCC","#CCFFFF","#FFCCCC",
            "#FFFF00","#CCCC00","#99CCFF","#FFCC33","#FFFFCC","#FFFF33","#99CCFF","#CCCCCC",
            "#FFFF00","#9933FF","#99CCFF","#FFCC33","#FFFF33","#FFCC00","#66CC00","#FFFF99",
            "#FF9900","#FFFF00","#0099CC","#FFCC00","#0000CC","#FFFF99","#CC9999","#FFFFCC",
            "#6666CC","#999933","#FFFFCC","#CC99CC","#CCCC00","#666600","#FFFF66","#FF9966",
            "#FFFFCC","#99CC99","#FFCC33","#FFFFCC","#999966","#FFCC99","#FF6666","#FFFF66",    //20
            "#FFCC99","#999966","#FFFF00","#FFFF99","#99CC99","#666600","#999966","#FFFF99",
            "#333333","#006633","#333300","#CCCC99","#006633","#663300","#CCCC66","#33CC33",
            "#6666CC","#CCCC33","#CCFFCC","#FFCC99","#CCFF99","#CCCCCC","#CCCC00","#999966",
            "#FFFFCC","#CCCC33","#336699","#CCCC33","#999999","#CCFFFF","#00CC00","#0066CC",
            "#99CCCC","#99CC33","#FF9900","#FFCC00","#99CC33","#CCCCFF","#663300","#CCCC33",
            "#993399","#CC6600","#999999","#CCCC33","#CC9933","#FFFF99","#99CC99","#669933",
            "#CCCC33","#663300","#99CC33","#CCCCCC","#CC6600","#CCCC33","#336699","#666600",
            "#CCCC66","#CCFFCC","#333366","#99CC33","#336699","#666666","#99CC33","#003366",
            "#003333","#99CC33","#999999","#996633","#FFFF99","#99CC66","#009966","#FFFF00",
            "#339933","#9933CC","#339933","#339933","#99CC00","#FFFFCC","#FFFFCC","#CCCC66",    //30
            "#336666","#99CC33","#FFFF66","#336600","#339933","#CC9900","#666666","#339966",
            "#CCCCCC","#003366","#669933","#CCCCCC","#339933","#CCCCCC","#6699CC","#006633",
            "#CCCC33","#CC9933","#339933","#666633","#CCCC66","#339933","#FFCC33","#336699",
            "#006633","#669933","#99CC99","#336666","#996633","#CCCC33","#003300","#669933",
            "#CCCC99","#006633","#990033","#FF9900","#006633","#333300","#CCCC99","#006633",
            "#663300","#CCCC66","#993333","#CC9966","#003300","#CCFF99","#66CCCC","#339999",
            "#99CCFF","#66CC99","#666699","#009999","#66CCCC","#CCFFFF","#66CCCC","#CCFF66",
            "#FF99CC","#339999","#FFFF00","#336699","#CC9933","#339999","#FFCC33","#FFCC00",
            "#009999","#CC3333","#669999","#CCCCCC","#CC99CC","#339999","#CCCCCC","#339999",
            "#666699","#CCCCCC","#003333","#99CC99","#FFFFCC","#669999","#CCFFCC","#996699",    //40
            "#996699","#CCCC99","#669999","#999966","#CCCC99","#339999","#336666","#669999",
            "#CCCC99","#999999","#003366","#669999","#663333","#339999","#CCCC66","#333333",
            "#339999","#CCFFCC","#336666","#3399CC","#666666","#FFFFCC","#FFFF99","#CCCCFF",
            "#9999CC","#99CC99","#FFCCCC","#CCCCFF","#CCCC99","#9999CC","#FFFFCC","#FFCCCC",
            "#FFCCCC","#FF99CC","#CCCCFF","#660066","#663333","#CCCC99","#333333","#9966CC",
            "#CCCC00","#FF9966","#663399","#996699","#FFCCCC","#CC99CC","#996666","#CC99CC",
            "#FFCCCC","#FFCC99","#FF9933","#663366","#333399","#CCCCFF","#CC99CC","#663366",
            "#CCCCCC","#CC99CC","#996699","#9999CC","#CCCCFF","#CC9966","#999999","#663366",
            "#330033","#666666","#669999","#CCCCCC","#999999","#663366","#FF33CC","#CCCC99",
            "#663366","#663366","#999999","#CCCCFF","#999966","#993333","#330033","#663366"     //50 -> 50*8 = 400
        };
        /// <summary>
        /// 得到一个序列颜色字符串值
        /// </summary>
        /// <returns></returns>
        public static string GetRandomColor(int idx)
        {
            if (++idx > 399) idx = 0;
            return VonColorDefine[idx];
        }
        /// <summary>
        /// 将指定颜色转换为Hsl格式的值
        /// </summary>
        /// <param name="AColor"></param>
        /// <returns>Hsl值数组，第一位为色相，第二位为饱和度，第三位为亮度</returns>
        public static double[] RgbToHsl(System.Drawing.Color AColor)
        {
            double r = AColor.R;
            double g = AColor.G;
            double b = AColor.B;
            if (r < 0) r = 0;
            if (g < 0) g = 0;
            if (b < 0) b = 0;
            if (r > 255) r = 255;
            if (g > 255) g = 255;
            if (b > 255) b = 255;
            r = r / 255;
            g = g / 255;
            b = b / 255;
            double M = Math.Max(Math.Max(r, g), b);
            double m = Math.Min(Math.Min(r, g), b);
            double d = M - m;
            double H, S, L;
            if (d == 0) H = 0;
            else if (M == r) H = ((g - b) / d) % 6;
            else if (M == g) H = (b - r) / d + 2;
            else H = (r - g) / d + 4;
            H *= 60;
            if (H < 0) H += 360;
            L = (M + m) / 2;
            if (d == 0)
                S = 0;
            else
                S = d / (1 - Math.Abs(2 * L - 1));  //如果放大或者缩小  乘以或者除以相应的倍数
            S = S * 255;
            L = L * 255;
            return new double[] { H, S, L };
        }
        /// <summary>
        /// 将Hsl颜色转换为RGB系统颜色
        /// </summary>
        /// <param name="Hue">色相</param>
        /// <param name="Saturation">饱和度</param>
        /// <param name="Lightness">亮度</param>
        /// <returns>系统颜色</returns>
        public static System.Drawing.Color HslToRgb(double Hue, double Saturation, double Lightness)
        {
            if (Hue < 0) Hue = 0.0;
            if (Saturation < 0) Saturation = 0.0;
            if (Lightness < 0) Lightness = 0.0;
            if (Hue >= 360) Hue = 359.0;
            if (Saturation > 255) Saturation = 255;
            if (Lightness > 255) Lightness = 255;
            Saturation = Saturation / 255.0;
            Lightness = Lightness / 255.0;
            double C = (1 - Math.Abs(2 * Lightness - 1)) * Saturation;
            double hh = Hue / 60.0;
            double X = C * (1 - Math.Abs(hh % 2 - 1));
            double r = 0, g = 0, b = 0;
            if (hh >= 0 && hh < 1)
            {
                r = C;
                g = X;
            }
            else if (hh >= 1 && hh < 2)
            {
                r = X;
                g = C;
            }
            else if (hh >= 2 && hh < 3)
            {
                g = C;
                b = X;
            }
            else if (hh >= 3 && hh < 4)
            {
                g = X;
                b = C;
            }
            else if (hh >= 4 && hh < 5)
            {
                r = X;
                b = C;
            }
            else
            {
                r = C;
                b = X;
            }
            double m = Lightness - C / 2;
            r += m;
            g += m;
            b += m;
            r = r * 255.0;
            g = g * 255.0;
            b = b * 255.0;
            r = Math.Round(r);
            g = Math.Round(g);
            b = Math.Round(b);
            return System.Drawing.Color.FromArgb((int)r, (int)g, (int)b);
        }
        /// <summary>
        /// 根据当前颜色获取下一个系列颜色
        /// </summary>
        /// <param name="current">当前颜色</param>
        /// <param name="part">颜色差异组数</param>
        /// <returns>计算后的系列颜色值</returns>
        public static System.Drawing.Color GetNextColor(System.Drawing.Color current, int part = 7)
        {
            double[] hsl = RgbToHsl(current);
            var rate = Math.Round(360.00 / (part * 2 + 1)) * 2;
            hsl[0] = (hsl[0] + rate) % 360;
            return HslToRgb(hsl[0], hsl[1], hsl[2]);
        }
        /// <summary>
        /// 根据当前颜色获取适应的字体颜色
        /// </summary>
        /// <param name="current">当前颜色</param>
        /// <returns>计算后的字体颜色值</returns>
        public static System.Drawing.Color GetFontColor(System.Drawing.Color current)
        {
            if (0.213 * current.R + 0.715 * current.G + 0.072 * current.B > 255 / 2) return System.Drawing.Color.Black;
            else return System.Drawing.Color.White;
        }
        #endregion
        #region "算法函数"
        /// <summary>
        /// 乱序算法
        /// </summary>
        /// <param name="crcValue">准备计算的cec信息</param>
        /// <returns></returns>
        public static T[] Disorder<T>(T[] Data, int n = 20)
        {
            Random rnd = new Random();
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<Data.Length;j++)
                {
                    T a = Data[j];
                    var idx = rnd.Next(Data.Length);
                    Data[j] = Data[idx];
                    Data[idx] = a;
                }
            }
            return Data;
        }
        /// <summary>
        /// Crc值计算
        /// </summary>
        /// <param name="crcInfo">准备计算的cec信息</param>
        /// <returns></returns>
        public static string CRC(String crcInfo)
        {
            System.Security.Cryptography.SHA1 sha = System.Security.Cryptography.SHA1.Create();
            return BytesToStr(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(crcInfo)));
        }
        /// <summary>
        /// Crc值计算
        /// </summary>
        /// <param name="crcValue">准备计算的cec信息</param>
        /// <returns></returns>
        public static string CRC(byte[] crcValue)
        {
            System.Security.Cryptography.SHA1 sha = System.Security.Cryptography.SHA1.Create();
            return BytesToStr(sha.ComputeHash(crcValue));
        }
        #endregion
        #region "文件相关函数"
        /// <summary>
        /// 压缩一个文件
        /// </summary>
        /// <param name="srcFile">原始文件</param>
        /// <param name="zipFile">压缩到的目标文件</param>
        public static void compressionFile(string srcFile, string zipFile)
        {
            FileInfo fileToCompress = new FileInfo(srcFile);
            if ((File.GetAttributes(fileToCompress.FullName) & FileAttributes.Hidden) != FileAttributes.Hidden)
            {
                using (FileStream originalFileStream = fileToCompress.OpenRead())
                {
                    using (FileStream compressedFileStream = File.Create(zipFile))
                    {
                        using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
                        {
                            originalFileStream.CopyTo(compressionStream);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 解压缩一个文件
        /// </summary>
        /// <param name="srcFile">压缩过的zip文件</param>
        /// <param name="orgFile">解压成的目标文件</param>
        public static void decompressionFile(string srcFile, string orgFile)
        {
            FileInfo fileToDecompress = new FileInfo(srcFile);
            using (FileStream originalFileStream = fileToDecompress.OpenRead())
            {
                string currentFileName = fileToDecompress.FullName;
                using (FileStream decompressedFileStream = File.Create(orgFile))
                {
                    using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
                    {
                        decompressionStream.CopyTo(decompressedFileStream);
                    }
                }
            }
        }
        /// <summary>
        /// 解析Json文件
        /// </summary>
        /// <param name="filename">文件路径</param>
        /// <returns></returns>
        public static JObject LoadJsonFile(string filename)
        {
            if (!File.Exists(filename)) return null;
            JObject config_object = null;
            try
            {
                StreamReader sr = new StreamReader(filename, Encoding.Default);
                config_object = JObject.Parse(sr.ReadToEnd());
                sr.Close();
            }
            catch { }
            return config_object;
        }
        /// <summary>
        /// 保存Json文件
        /// </summary>
        /// <param name="json">json对象</param>
        /// <param name="filename">文件路径</param>
        /// <returns></returns>
        public static void SaveJsonFile(JObject json, string filename)
        {
            try
            {
                StreamWriter sr = new StreamWriter(filename, false, Encoding.Default);
                sr.Write(Newtonsoft.Json.JsonConvert.SerializeObject(json));
                sr.Close();
            }
            catch { }
        }
        /// <summary>
        /// 获取文件后缀
        /// </summary>
        /// <param name="filename">文件名</param>
        /// <returns>文件后缀（含点）</returns>
        public static string GetFileExt(string filename)
        {
            var idx = filename.LastIndexOf('.');
            if (idx < 0) return "";
            return filename.Substring(idx);
        }
        #endregion
        #region "检测相关函数"
        /// <summary>
        /// 判断输入的字符串是否是一个合法的手机号
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsMobile(string input)
        {
            Regex regex = new Regex("^13\\d{9}$");
            return regex.IsMatch(input);

        }
        /// <summary>
        /// 判断是否为数字字符串
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public static bool isNumberic(string numStr)
        {
            for (int i = 0; i < numStr.Length; i++)
            {
                if (numStr[i] <= '0' || numStr[i] >= '9')
                    return false;
            }
            return true;
        }
        #endregion
        #region "日期、时间相关函数"
        /// <summary>
        /// 获取指定日期当月第一天
        /// </summary>
        /// <param name="dt">指定时间</param>
        /// <reutrn>返回第几周</reutrn>
        public static DateTime GetFirstOfMonth(DateTime dt)
        {
            return new DateTime(dt.Year, dt.Month, 1);
        }
        /// <summary>
        /// 获取指定日期当月第一天
        /// </summary>
        /// <param name="dt">指定时间</param>
        /// <reutrn>返回第几周</reutrn>
        public static DateTime GetFirstOfYear(DateTime dt)
        {
            return new DateTime(dt.Year, 1, 1);
        }
        /// <summary>
        /// 获取指定日期，在为一年中为第几周
        /// </summary>
        /// <param name="dt">指定时间</param>
        /// <reutrn>返回第几周</reutrn>
        public static int GetWeekOfYear(DateTime dt)
        {
            GregorianCalendar gc = new GregorianCalendar();
            int weekOfYear = gc.GetWeekOfYear(dt, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
            return weekOfYear;
        }
        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public static long TimeStamp()
        {
            return (long)((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds * 100);
        }
        public static string LonLatToStr(Decimal lon)
        {
            Decimal l1 = Math.Truncate(lon);
            Decimal lz = (lon - l1) * 60;
            Decimal l2 = Math.Truncate(lz);
            lz = (lz - l2) * 60;
            return string.Format("{0:#}度{1:#}分{2:#.####}秒", l1, l2, lz);
        }

        /// <summary>
        /// 将dateTime格式转换为Unix时间戳
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static double DateTimeToUnixTime(DateTime dateTime)
        {
            return (double)(dateTime - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1))).TotalMilliseconds;
        }

        /// <summary>
        /// 将Unix时间戳转换为dateTime格式
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static DateTime UnixTimeToDateTime(double milliseconds)
        {
            if (milliseconds < 0)
                throw new ArgumentOutOfRangeException("time is out of range");

            return TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).AddMilliseconds(milliseconds);
        }
        /// <summary>
        /// 将Unix时间戳转换为dateTime格式
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static DateTime SecondToDateTime(double seconds)
        {
            if (seconds < 0)
                throw new ArgumentOutOfRangeException("time is out of range");

            return (new DateTime(1970, 1, 1)).AddSeconds(seconds);
        }
        #endregion
        #region "单元格转换"

        public static bool SplitCellName(string CellName, out int col, out int row, out bool rowLocked, out bool colLocked)
        {
            int idx = 0, iPos = -1; row = 0; col = 0; rowLocked = false; colLocked = false;
            if (CellName[idx] == '$') { colLocked = true; idx++; }
            while (idx < CellName.Length)
            {
                iPos = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".IndexOf(CellName[idx]) + 1;
                if (iPos > 0) { col = col * 26 + (iPos > 26 ? iPos - 26 : iPos); idx++; }
                else break;
            }
            if (idx == CellName.Length || col == 0) return false;
            if (CellName[idx] == '$') { rowLocked = true; idx++; }
            while (idx < CellName.Length)
            {
                iPos = "0123456789".IndexOf(CellName[idx]);
                if (iPos > 0) { row = row * 10 + iPos; idx++; }
                else break;
            }
            if (idx < CellName.Length || row == 0) return false;
            col--;
            row--;
            return true;
        }
        public static string CellName(int col, int row, bool rowLocked, bool colLocked)
        {
            string result = "";
            do
            {
                result = (char)(col % 26 + 65) + result;
                col = col / 26;
            } while (col > 0);
            return (colLocked ? "$" : "" ) + result + (rowLocked ? "$" : "") + (row + 1).ToString();
        }
        public static bool SplitCellName(string CellName, out int col, out int row)
        {
            int idx = 0, iPos = -1; row = 0; col = 0;
            while (idx < CellName.Length)
            {
                iPos = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".IndexOf(CellName[idx]) + 1;
                if (iPos > 0) { col = col * 26 + (iPos > 26 ? iPos - 26 : iPos); idx++; }
                else break;
            }
            if (idx == CellName.Length || col == 0) return false;
            while (idx < CellName.Length)
            {
                iPos = "0123456789".IndexOf(CellName[idx]);
                if (iPos > 0) { row = row * 10 + iPos; idx++; }
                else break;
            }
            if (idx < CellName.Length || row == 0) return false;
            col--;
            row--;
            return true;
        }
        public static string CellName(int col, int row)
        {
            string result = "";
            do
            {
                result = (char)(col % 26 + 65) + result;
                col = col / 26;
            } while (col > 0);
            if(row >= 0) return result + (row + 1).ToString();
            return result;
        }
        #endregion
        public static void AddJson(JObject Data, string key, Object obj)
        {
            string[] ks = key.Split('.');
            JObject item = Data;
            int i = 0;
            while (i < ks.Length - 1)
            {
                if (item[ks[i]] == null) break;
                item = (JObject)item[ks[i++]];
            }
            if (i == ks.Length - 1)
            {
                if (item[ks[ks.Length - 1]] != null) item.Remove(ks[ks.Length - 1]);
                item.Add(new JProperty(ks[ks.Length - 1], obj));
            }
            else
            {
                JObject newItem = new JObject();
                newItem.Add(new JProperty(ks[ks.Length - 1], obj)); //(SSS, obj)
                for (int idx = ks.Length - 2; idx > i; idx--)                 //AAA.BBB.CCC->(3..1)->
                {
                    JObject szItem = new JObject();
                    szItem.Add(ks[idx], newItem);
                    newItem = szItem;
                }
                item[ks[i]] = newItem;
            }
        }
        public static object GetJsonValue(JObject Variables, string key)
        {
            string[] ks = key.Split('.');
            JObject obj = Variables;
            for (int i = 0; i < ks.Length - 1; i++)
            {
                obj = (JObject)obj[ks[i]];
                if (obj == null) return null;
            }
            JValue vl = (JValue)obj[ks[ks.Length - 1]];
            if (vl == null) throw new Exception("Error on get value by " + key + " of calculation");
            switch (vl.Type)
            {
                case JTokenType.Integer: return (double)vl.Value<int>();
                case JTokenType.Date: return vl.Value<DateTime>();
                case JTokenType.Boolean: return vl.Value<bool>();
                case JTokenType.Float: return vl.Value<double>();
                default: return vl.ToString();
            }
        }
    }
}